#include "iomanager.h"
#include "macro.h"
#include <unistd.h>
#include "log.h"
#include <fcntl.h>

//    int epoll_wait(int epfd, struct epoll_event *events,
//                   int maxevents, int timeout);
//    int epoll_pwait(int epfd, struct epoll_event *events,
//                   int maxevents, int timeout,
//                   const sigset_t *_Nullable sigmask);
//    int epoll_pwait2(int epfd, struct epoll_event *events,
//                   int maxevents, const struct timespec *_Nullable timeout,
//                   const sigset_t *_Nullable sigmask);

//    #include <sys/epoll.h>

//    int epoll_ctl(int epfd, int op, int fd,
//                  struct epoll_event *_Nullable event);
//    int fcntl(int fd, int cmd, ... /* arg */ );
namespace sylar
{
    static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
    IOManager::IOManager(size_t thread_num, bool use_caller, const std::string &name) : Scheduler(thread_num, use_caller, name)
    {
        m_epfd = epoll_create(1);
        SYLAR_ASSERT(m_epfd > 0);
        int rt = pipe(m_tickleFds);
        SYLAR_ASSERT(rt);
        epoll_event event;
        memset(&event, 0, sizeof(epoll_event));
        event.events = EPOLLIN | EPOLLET;
        event.data.fd = m_tickleFds[0];
        rt = fcntl(m_tickleFds[0], F_SETFL, O_NONBLOCK);
        SYLAR_ASSERT(!rt);
        rt = epoll_ctl(m_epfd, EPOLL_CTL_ADD, m_tickleFds[0], &event);
        SYLAR_ASSERT(!rt);
        contextResize(32);
        start();
    }
    IOManager::~IOManager()
    {
        stop();
        close(m_epfd);
        close(m_tickleFds[0]);
        close(m_tickleFds[1]);
        for (size_t i = 0; i < m_fdContexts.size(); ++i)
        {
            if (m_fdContexts[i])
            {
                delete m_fdContexts[i];
            }
        }
    }
    int IOManager::addEvent(int fd, IOManager::Event event, std::function<void()> cb = nullptr)
    {
        FdContext *fd_ctx = nullptr;

        RWMutexType::WriteLock lock(m_mutex);
        if (m_fdContexts.size() > fd)
        {
            fd_ctx = m_fdContexts[fd];
        }
        else
        {
            lock.unlock();
            RWMutexType::WriteLock lock2(m_mutex);
            size_t cur_size = m_fdContexts.size();
            while (cur_size <= fd)
            {
                cur_size *= 1.5;
            }
            contextResize(cur_size);
            fd_ctx = m_fdContexts[fd];
        }

        FdContext::MutexType::Lock lock3(fd_ctx->mutex);
        if(fd_ctx->m_events & event)
        {
            SYLAR_LOG_ERROR(g_logger)<< "error: IOManager::addEvent";
        }

    }
    // 1 ok 0 retry -1 error
    bool IOManager::delEvent(int fd, IOManager::Event event)
    {
    }
    bool IOManager::cancelEvent(int fd, IOManager::Event event)
    {
    }
    bool IOManager::cancleAll(int fd)
    {
    }
    IOManager *IOManager::GetThis()
    {
    }
    void IOManager::contextResize(size_t size)
    {
        m_fdContexts.resize(size);
        for (size_t i = 0; i < m_fdContexts.size(); ++i)
        {
            m_fdContexts[i] = new FdContext;
            m_fdContexts[i]->fd = i;
        }
    }

    //         void tickle() override;
    // bool stopping() override;
    // void idle() override;
}